from django.shortcuts import render,redirect
#导包
from django.http import HttpResponse,HttpResponseRedirect,JsonResponse
#导入类视图
from django.views import View

import json
from django.core.serializers import serialize
from rest_framework.response import Response
from rest_framework.views import APIView
#导入加密库
import hashlib
#导入图片库
#绘画库
from PIL import ImageDraw
#字体库
from PIL import ImageFont
#图片库
from PIL import Image
#随机库
import random
#文件流
import io

import requests

#导入上传文件夹配置
from mydjango.settings import UPLOAD_ROOT
import os

#导入原生sql模块
from django.db import connection

import jwt

#导入redis数据库
import redis

#导入时间模块
import time

#导入公共目录变量
from mydjango.settings import BASE_DIR

#导包
from django.db.models import Q,F

#导入dwebsocket的库
from dwebsocket.decorators import accept_websocket
import uuid

from myapp.models import User

from django.utils.deprecation import MiddlewareMixin

from django.http import QueryDict


#类视图调用
from django.utils.decorators import method_decorator

#事务操作
from django.db import transaction



#锁的使用
def testlock(request):

	res = User.objects.get(pk=1)

	if res.num > 0:
		time.sleep(5)
		with connection.cursor() as c:
			c.execute(' update user set num = num - 1 where id = 1 ')
		return HttpResponse("ok")
	else:
		return HttpResponse("钱包为空")




#并发操作
def TestThread(request):

	res = User.objects.get(pk=1)

	if res.num > 0:
		time.sleep(5)
		# with connection.cursor() as c:
		# 	c.execute('update user set num = num - 1 where id = 1 ')

		#事务
		try:
			with transaction.atomic():
				res.num = 9
				res.save()
		except ValueError:
			pass

		return HttpResponse("ok")
	else:
		return HttpResponse("库存不足")





#websocket接口
#客户端列表
clients = {}
@accept_websocket
def websocketlink(request):

	if request.is_websocket():

		userid = str(uuid.uuid1())

		while True:

			message = request.websocket.wait()

			if not message:
				break
			else:
				print('websocket链接成功'+str(message))
				clients[userid] = request.websocket

#推送消息
def sendmessage(request):

	#获取消息
	msg = request.GET.get("msg")

	for client in clients:
		clients[client].send(msg.encode('utf-8'))

	return HttpResponse({'message':"ok"})


r = redis.Redis(host="localhost")
#获取客户端ip
class GetOnLines(APIView):

	def get(self,request):

		if "HTTP_X_FORWARDED_FOR" in request.META:

			ip = request.META.get("HTTP_X_FOGWARDED_FOR")

		else:
			ip = request.META.get("REMOTE_ADDR")

		if r.scard("set_ip"):

			r.sadd("set_ip",ip)
		else:
			r.sadd("set_ip",ip)
			r.expire("set_ip",30)

		return Response({"online":r.scard("set_ip")})





import time
import hmac
import base64
from hashlib import sha256
import urllib
import json

#构造钉钉回调方法
def ding_back(request):

    #获取code
    code = request.GET.get("code")

    t = time.time()
    #时间戳
    timestamp = str((int(round(t * 1000))))
    appSecret ='ly-AzMKMmCKQP3geaILT_An32kEfKO3HeOtApy5CgKwjytevVZC0WYsT2gxMB160'
    #构造签名
    signature = base64.b64encode(hmac.new(appSecret.encode('utf-8'),timestamp.encode('utf-8'), digestmod=sha256).digest())
    #请求接口，换取钉钉用户名
    payload = {'tmp_auth_code':code}
    headers = {'Content-Type': 'application/json'}
    res = requests.post('https://oapi.dingtalk.com/sns/getuserinfo_bycode?signature='+urllib.parse.quote(signature.decode("utf-8"))+"&timestamp="+timestamp+"&accessKey=dingoaukgkwqknzjvamdqh",data=json.dumps(payload),headers=headers)

    res_dict = json.loads(res.text)
    print(res_dict)

    #判断
    user = User.objects.filter(username=res_dict['userinfo']['nick'])

    if user:

    	return redirect('http://localhost:8080/staition?uid='+user.id+"&username="+user.username)

    else:

    	user = User(username=res_dict['userinfo']['nick'])
    	user.save()
    	user = User.objects.filter(username=res_dict['userinfo']['nick'])

    	return redirect('http://localhost:8080/staition?uid='+user.id+"&username="+user.username)


#钉钉
class Dingding:

	def get_url(self,appid,redirect_uri):

		return 'https://oapi.dingtalk.com/connect/qrconnect?appid='+appid+'&response_type=code&scope=snsapi_login&state=STATE&redirect_uri='+redirect_uri


#工厂类
class LoginFactory:

	@staticmethod
	def login_cls(type):
		if type == 'dingding':
			return Dingding()

def dictfetchall(cursor):
    desc = cursor.description
    return [
    dict(zip([col[0] for col in desc], row)) 
    
    for row in cursor.fetchall()
    
    ]

#执行原生sql
def get_access(request):

	uid = request.GET.get("uid",None)

	#获取游标对象
	cursor = connection.cursor()

	#执行sql
	cursor.execute(" select a.username,d.nodename from user a left join role b on a.role_id = b.id left join access c on b.id = c.role_id left join node d on c.node_id = d.id ")
	
	result = dictfetchall(cursor)

	print(result)

	return HttpResponse(json.dumps(result,ensure_ascii=False),content_type='application/json')


#装饰器
def my_decorator(func):
	def wrapper(request,*args,**kwargs):


		print('装饰器被调用了')

		return func(request,*args,**kwargs)

	return wrapper



#拼接url
#构造钉钉登录url
def ding_url(request):

	ding_obj = LoginFactory.login_cls('dingding')
	url = ding_obj.get_url('123','123')
	return redirect(url)

    # appid = 'dingoaukgkwqknzjvamdqh'
    # redirect_uri = 'http://localhost:8000/dingding_back/'

    # return redirect('https://oapi.dingtalk.com/connect/qrconnect?appid='+appid+'&response_type=code&scope=snsapi_login&state=STATE&redirect_uri='+redirect_uri)

#注册接口
class Register(APIView):

	def post(self,request):

		#接收参数
		username = request.POST.get("username",None)

		print(username)
		

		#唯一性验证
		try:
			user = User(username=username,password="123")
			user.save()
			response = Response({'message':'注册成功'})
			response["Access-Control-Allow-Origin"] = "http://localhost:8080"
			return response
		except Exception as e:
			print(e)
			response = Response({'message':'注册失败'})
			response["Access-Control-Allow-Origin"] = "http://localhost:8080"
			return response


	# def put(self,request):

	# 	#接收参数
	# 	put = QueryDict(request.body)
	# 	username = put.get('username',None)

	# @method_decorator(my_decorator)
	# def delete(self,request):

	# 	put = QueryDict(request.body)
	# 	for key,val in put.items():
	# 		username = eval(key)['username']




class MyMiddleware(MiddlewareMixin):

	def process_request(self, request):

		pass
		#return HttpResponse(json.dumps({'message':'您没有权限'},ensure_ascii=False))

	def process_view(self, request, view_func, view_args, view_kwargs):
	    pass

	def process_exception(self, request, exception):
	    pass

	def process_response(self, request, response):
	    return response


#上传类
class UploadFile(View):

	#上传方法
	def post(self,request):

		#接收参数
		img = request.FILES.get("file")

		#建立文件流
		# f = open(os.path.join(UPLOAD_ROOT,'',img.name),'wb')

		# #写文件
		# for chunk in img.chunks():
		# 	f.write(chunk)

		# #关闭文件流
		# f.close()
		with open(os.path.join(UPLOAD_ROOT,'',img.name),'wb') as f:
			#写文件
			for chunk in img.chunks():
				f.write(chunk)


		return HttpResponse(json.dumps({'filename':img.name},ensure_ascii=False),content_type='application/json')

clients={} #创建客户端列表，存储所有在线客户端
@accept_websocket
def link(request):
    # 判断是不是ws请求
    if request.is_websocket():
        userid=str(uuid.uuid1())
        # 判断是否有客户端发来消息，若有则进行处理，若发来“test”表示客户端与服务器建立链接成功
        while True:
            message=request.websocket.wait()
            if not message:
                break
            else:
                print("客户端链接成功："+str(message, encoding = "utf-8"))
                #保存客户端的ws对象，以便给客户端发送消息,每个客户端分配一个唯一标识
                clients[userid]=request.websocket




#定义验证码类
class Myc(View):
	#定义随机颜色方法
	def get_random_color(self):
	    R = random.randrange(255)
	    G = random.randrange(255)
	    B = random.randrange(255)
	    return (R,G,B)
	#定义随机验证码
	def get(self,request):
	    #定义画布大小 宽，高
	    img_size = (120,50)
	    #定义画笔 颜色种类,画布，背景颜色
	    image = Image.new("RGB",img_size,'white')
	    #定义画笔对象 图片对象,颜色类型
	    draw = ImageDraw.Draw(image,'RGB')
	    #定义随机字符
	    source = '0123456789asdfghjkl'
	    #定义四个字符
	    #定义好容器，用来接收随机字符串
	    code_str = ''
	    for i in range(4):
	        #获取随机颜色 字体颜色
	        text_color = self.get_random_color()
	        #获取随机字符串
	        tmp_num = random.randrange(len(source))
	        #获取字符集
	        random_str = source[tmp_num]
	        #将随机生成的字符串添加到容器中
	        code_str += random_str
	        #将字符画到画布上 坐标，字符串，字符串颜色，字体
	        #导入系统真实字体,字号
	        #my_font = ImageFont.truetype("c:\\windows\\Fonts\\arial.ttf",20)
	        draw.text((10+30*i,20)
	        ,random_str,text_color)
	    #使用io获取一个缓存区
	    buf = io.BytesIO()
	    #将图片保存到缓存区
	    image.save(buf,'png')

	    #将随机码存储到session中
	    request.session['code'] = code_str

	    #第二个参数声明头部信息
	    return HttpResponse(buf.getvalue(),'image/png')